import requests
import json
import re
import os
from pprint import pprint as pp
import queue


class DouYin:
    header = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'max-age=0',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
    }

    def __init__(self, url=None):
        user_share_url=input('个人名片分享所得链接： ') 
        self.choose_user_share_url=int(input('1-只下载用户上传，2-只下载用户喜欢的，3-两者都下载，默认都下载： '))
        self.digg_count=int(input('下载获赞数超过多少的视频/个赞 ：'))
        if (self.choose_user_share_url in [1,2,3]) == False:
            self.choose_user_share_url = 3
        self.url = self.get_RealAddress(user_share_url)
        self.user_video_url = 'https://www.douyin.com/aweme/v1/aweme/post/?{0}'
        self.favorite_url = 'https://www.amemv.com/aweme/v1/aweme/favorite/?{0}'
        self.user_id = re.search(r'user/(.*)\?', self.url).group(1)     # 用户id  
        requests.packages.urllib3.disable_warnings()
        self.session = requests.Session()
        self.target_folder = ''     # 创建文件的路径
        self.queue = queue.Queue()      # 生成一个队列对象

    # 获取个人信息以及视频列表
    def user_info(self):
        self.mkdir_dir()  # 创建对应的文件夹
        p = os.popen('node douyin_signature.js %s' % self.user_id)  # 获取加密的signature
        signature = p.readlines()[0]
        ydtk = self.get_dytk()
        

        user_video_params = {
            'user_id': str(self.user_id),
            'count': '21',
            'max_cursor': '0',
            'aid': '1128',
            '_signature': signature,
            'dytk': self.get_dytk(),
        }
       
        # 获取账户的视频列表
        def get_aweme_list(get_aweme_video_list_url,max_cursor=None):
            if max_cursor:
                user_video_params['max_cursor'] = str(max_cursor)
            user_video_url = get_aweme_video_list_url.format('&'.join([key + '=' + user_video_params[key] for key in user_video_params]))    # 拼接参数
            response = requests.get(url=user_video_url, headers=self.header, verify=False)
            contentJson = json.loads(response.content.decode('utf-8'))  # 将返回的进行utf8编码
            aweme_list = contentJson.get('aweme_list', [])
            if aweme_list == []:
                print('好遗憾，我他娘的没有找到')
                return
            else:#   http://v.douyin.com/eD9vtV/
                for aweme in aweme_list:
                    str_digg_count = str(aweme.get('statistics',None).get('digg_count',None))
                    if str_digg_count.find('w') > 0:
                        digg_count =  float(str_digg_count.split('w')[0])*10000 
                    else:
                        digg_count =  float(str_digg_count)

                    if digg_count > self.digg_count:
                        pass
                        video_name = aweme.get('share_info', None).get('share_desc', None)     # 视频的名字
                        video_url = aweme.get('video', None).get('play_addr', None).get('url_list', None)[0].replace('playwm', 'play')      # 视频链接
                        self.queue.put((video_name, video_url))  # 将数据进队列
                if contentJson.get('has_more') == 1:    # 判断后面是不是还有是1就是还有
                    return get_aweme_list(get_aweme_video_list_url,contentJson.get('max_cursor'))    # 有的话获取参数max_cursor
        
        if self.choose_user_share_url == 1:
            get_aweme_list(self.user_video_url)
        elif self.choose_user_share_url == 2:
            get_aweme_list(self.favorite_url)
        else:
            get_aweme_list(self.user_video_url)
            get_aweme_list(self.favorite_url)

    # 下载视频
    def get_download(self):
        success_num = 1    
        err_num = 1
        while self.queue.empty()==False:
            video_name, video_url = self.queue.get()
            file_name = video_name + '.mp4'
            file_path = os.path.join(self.target_folder, file_name)
            if not os.path.isfile(file_path):
                # print('download %s form %s.\n' % (file_name, video_url))
                times = 0
                while times < 10:
                    try:
                        response = requests.get(
                            url=video_url, stream=True, timeout=10, verify=False)   # 开启流下载
                        with open(file_path, 'wb') as f:
                            for chunk in response.iter_content(1024):   # 返回迭代对象
                                f.write(chunk)
                            print('下载成功', success_num )
                            success_num += 1
                        break
                    except:
                        print('下载失败', err_num )
                        err_num += 1
                    times += 1

        print('\n'.join(
        [''.join([('Love'[(x-y) % len('Love')] 
            if ((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3 <= 0 else ' ')for x in range(-30, 30)]) 
        for y in range(30, -30, -1)]))
        print('++++++++++++++++++++++++视频全部下载完成+++++++++++++++')

    # 创建对应的文件夹
    def mkdir_dir(self):
        current_folder = os.getcwd()
        self.target_folder = os.path.join(
            current_folder, 'download/%s' % self.user_id)
        if not os.path.isdir(self.target_folder):
            os.mkdir(self.target_folder)

    # 短链接转长地址
    def get_RealAddress(self, url):
        if url.find('v.douyin.com') < 0:
            return url
        response = requests.get(
            url=url, headers=self.header, allow_redirects=False)  # allow_redirects 允许跳转
        return response.headers['Location']
    #获取dytk
    def get_dytk(self):
        url = 'https://www.douyin.com/share/user/'+str(self.user_id)+'?share_type=link'
        response = requests.get(url=url,headers=self.header, allow_redirects=True)
        dytk = response.content.decode('utf-8').split("dytk:")[1].split('})')[0].split("'")[1]
        return str(dytk)

if __name__ == '__main__':
    douyin = DouYin()
    douyin.user_info()
    douyin.get_download()


